package com.iflyings.android.component

interface ComponentContext {

    //操作符[]重载，可以通过ComponentContext[Key]这种形式来获取与Key关联的Element
    operator fun <E: Element> get(key: Key<E>): E? = first { return@first key == it.key }

    //它是一个聚集函数，提供了从left到right遍历CoroutineContext中每一个Element的能力，并对每一个Element做operation操作
    fun <R> fold(initial: R, operation: (R, Element) -> R): R

    fun <E: Element> first(operation: (E) -> Boolean): E?

    //操作符+重载，可以ComponentContext + ComponentContext这种形式把两个ComponentContext合并成一个
    operator fun plus(context: ComponentContext) =
        if (context == EmptyComponentContext)
            this
        else // fast path -- avoid lambda creation
            context.fold(this) { acc, element ->
                val removed = acc.minusKey(element.key)
                if (removed == EmptyComponentContext) {
                    element
                } else {
                    CombinedComponentContext(removed, element)
                }
            }

    operator fun minus(context: ComponentContext): ComponentContext {
        return if (context == EmptyComponentContext)
            this
        else
            context.fold(this) { acc, element ->
                acc.minusKey(element.key)
            }
    }

    //返回一个新的ComponentContext，这个ComponentContext删除了Key对应的Element
    fun minusKey(key: Key<*>): ComponentContext

    interface Key<E : Element>

    //Element定义，每个Element都是一个ComponentContext
    interface Element: ComponentContext {

        //每个Element都有一个Key实例
        val key: Key<*>

        override fun <R> fold(initial: R, operation: (R, Element) -> R): R = operation(initial, this)

        @Suppress("UNCHECKED_CAST")
        override fun <E: Element> first(operation: (E) -> Boolean): E? = if (operation(this as E)) this else null

        override fun minusKey(key: Key<*>): ComponentContext = if (this.key == key) EmptyComponentContext else this

    }
}

